package io.jpress.service.provider;

import com.jfinal.aop.Inject;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Record;
import io.jboot.aop.annotation.Bean;
import io.jboot.components.cache.AopCache;
import io.jboot.components.cache.annotation.Cacheable;
import io.jboot.service.JbootServiceBase;
import io.jboot.utils.ModelUtil;
import io.jpress.model.Department;
import io.jpress.model.SiteInfo;
import io.jpress.model.User;
import io.jpress.service.DepartmentService;
import io.jpress.service.RoleService;
import io.jpress.service.SiteInfoService;
import io.jpress.service.UserService;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 注意：此类不能继承 JPressServiceBase，否则其 site_id 字段将会被自动设置
 */
@Bean
public class SiteInfoServiceProvider extends JbootServiceBase<SiteInfo> implements SiteInfoService {

    @Inject
    private UserService userService;

    @Inject
    private RoleService roleService;

    @Inject
    private DepartmentService departmentService;


    @Override
    @Cacheable(name = "site_info")
    public List<SiteInfo> findAll() {
        return super.findAll();
    }

    /**
     * 插入 site 对应的 dept 信息
     *
     * @param siteId
     * @param deptIds
     * @return boolean
     */
    @Override
    public boolean saveSiteDeptInfos(@NotNull Long siteId, Long[] deptIds) {

        //查询对应的 site 是否有记录
        String sql = "select * from site_department_mapping where site_id = ?";
        Record first = Db.findFirst(sql, siteId);

        //如果有记录 删除
        if (first != null) {
            String dSql = "delete from site_department_mapping where site_id = ?";
            Db.delete(dSql, siteId);
        }

        //如果没有选择任何部门 没有必要保存
        if (deptIds != null && deptIds.length > 0) {
            //循环数组
            for (long deptId : deptIds) {
                //id 不能小于 0
                if (deptId > 0) {
                    Record record = new Record();
                    record.set("site_id", siteId);
                    record.set("dept_id", deptId);

                    Db.save("site_department_mapping", null, record);
                }
            }
        }

        return true;
    }


    @Override
    public Set<Long> findBindDeptIds(Long siteId) {
        String sql = "select * from site_department_mapping where site_id = ?";
        List<Record> recordList = Db.find(sql, siteId);
        if (recordList == null || recordList.isEmpty()) {
            return null;
        }

        return recordList.stream().map(record -> record.getLong("dept_id"))
                .collect(Collectors.toSet());
    }


    /**
     * 更加用户ID查找站点信息，此内容和部门id有关
     * 当部门信息更新的时候 {@link UserServiceProvider#updateDepartmentId(Long, Long)}，需要清除 site_info 缓存信息
     *
     * @param userId
     * @return
     */
    @Override
    @Cacheable(name = "site_info", key = "user:#(userId)")
    public List<SiteInfo> findByUserId(Long userId) {
        List<SiteInfo> siteInfos = doFindByUserId(userId);
        if (siteInfos == null) {
            siteInfos = new ArrayList<>();
        }

        //未分配站点的情况下，默认是主站点
        if (siteInfos.isEmpty()) {
            siteInfos.add(getMainSiteInfo());
        }

        return siteInfos;
    }


    public List<SiteInfo> doFindByUserId(Long userId) {
        User user = userService.findById(userId);
        if (user == null) {
            return null;
        }

        //超级管理员，返回全部，和绑定的部门无关
        if (roleService.isSupperAdmin(userId)) {
            List<SiteInfo> all = ModelUtil.copy(findAll());
            all.add(getMainSiteInfo());
            return all;
        }

        Department department = departmentService.findByUserId(userId);
        if (department == null) {
            return null;
        }

        String sql = "select * from site_department_mapping where dept_id = ?";
        List<Record> recordList = Db.find(sql, department.getId());

        if (recordList == null || recordList.isEmpty()) {
            return null;
        }

        return recordList.stream().map(record -> {
                    Long siteId = record.getLong("site_id");
                    return siteId == 0 ? getMainSiteInfo() : findById(siteId);
                })
                .collect(Collectors.toList());
    }


    private SiteInfo getMainSiteInfo() {
        SiteInfo siteInfo = new SiteInfo();
        siteInfo.setName("主站点");
        siteInfo.setSiteId(0L);
        return siteInfo;
    }


    @Override
    public void shouldUpdateCache(int action, Model model, Object id) {
        AopCache.removeAll("site_info");
    }
}